package io.github.shenbinglife.springboot2.layui.admin.service.impl;

import io.github.shenbinglife.springboot2.layui.admin.dao.RoleDao;
import io.github.shenbinglife.springboot2.layui.admin.entity.Role;
import io.github.shenbinglife.springboot2.layui.admin.entity.RoleMenuRelation;
import io.github.shenbinglife.springboot2.layui.admin.entity.User;
import io.github.shenbinglife.springboot2.layui.common.model.TreeNode;
import io.github.shenbinglife.springboot2.layui.common.service.impl.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.List;
import java.util.stream.Collectors;

@Transactional
@Service
public class RoleService extends BaseService<Role, RoleDao> {

    @Autowired
    private MenuService menuService;

    public Page<Role> page(String keyword, int page, Integer limit) {
        PageRequest pageRequest = PageRequest.of(page, limit, Sort.by(Sort.Order.desc("updateTime")));
        return baseDao.findByKeywordWithPagination(keyword, pageRequest);
    }

    public void deleteById(Long[] roleIds) {
        for (Long roleId : roleIds) {
            this.deleteById(roleId);
        }
    }

    public List<User> getRoleUsers(Long roleId) {
        return baseDao.findUsersByRoleId(roleId);
    }

    public List<Role> getUserRoles(Long userId) {
        return baseDao.findRolesByUserId(userId);
    }

    @Override
    public void deleteById(Long id) {
        baseDao.removeRelationByRoleId(id);
        super.deleteById(id);
    }

    public Page<User> getPageRoleUsers(Long roleId, String keyword, Integer page, Integer limit) {
        PageRequest pageRequest = PageRequest.of(page, limit, Sort.by(Sort.Order.asc("account")));
        return baseDao.findUsersByRoleIdWithPagination(roleId, keyword, pageRequest);
    }

    public void addUsersToRole(Long roleId, Long... userIds) {
        baseDao.addUserToRole(roleId, userIds);
    }

    public void removeUsersFromRole(Long roleId, Long[] userIds) {
        for (Long userId : userIds) {
            baseDao.removeUsersFromRole(roleId, userId);
        }
    }

    public void removeRelationByUserId(Long userId) {
        baseDao.removeRelationByUserId(userId);
    }

    public List<Role> getRoleByScope(String scope) {
        return baseDao.findByScope(scope);
    }

    public void updateEnabled(Long roleId, Boolean enabled) {
        baseDao.updateEnabled(roleId, enabled);
    }

    public List<TreeNode<Long>> getMenuTrees(Long roleId) {
        List<RoleMenuRelation> roleMenuRelations = baseDao.findMenusByRoleId(roleId);
        List<Long> menuIds = roleMenuRelations.stream()
                .map(RoleMenuRelation::getMenuId)
                .collect(Collectors.toList());
        List<TreeNode<Long>> menuTree = menuService.getMenuTree(-1l, true);
        for (TreeNode<Long> treeNode : menuTree) {
            treeNode.resolveDown((item) -> {
                TreeNode<Long> node =  (TreeNode<Long>)  item;
                if (menuIds.contains(node.getId())) {
                    node.setChecked(true);
                }
            });
        }
        return menuTree;
    }

    public void saveRoleMenus(Long roleId, Long[] menuIds){
        baseDao.removeMenuRelationByRoleId(roleId);
        baseDao.addMenuToRole(roleId, menuIds);
    }
}
